

#ifndef FNB_SMART_PTR_H
#define FNB_SMART_PTR_H



template <typename T>
class wxFNBSmartPtr
{
	typedef T* type_ptr;

	
	class SmartPtrRef
	{
		type_ptr m_data;
		int m_refCount;

	public:
		
		SmartPtrRef(type_ptr data)
			: m_data( data )
			, m_refCount( 1 )
		{
		}

		
		virtual ~SmartPtrRef()
		{
			delete m_data;
		}

		
		type_ptr GetData() { return m_data; }

		
		void IncRef() { m_refCount ++ ; }


		
		void DecRef() { m_refCount -- ; }
		
		int  GetRefCount() { return m_refCount; }
	};

	SmartPtrRef *m_ref;

public:
	
	wxFNBSmartPtr(type_ptr ptr)
	{
	
		CreateFresh( ptr );
	}
	
	
	wxFNBSmartPtr()
		: m_ref(NULL)
	{
	}

	
	wxFNBSmartPtr(const wxFNBSmartPtr& rhs)
		: m_ref(NULL)
	{
		*this = rhs;
	}

	
	wxFNBSmartPtr& operator=(const wxFNBSmartPtr& rhs)
	{
	
		if( m_ref == rhs.m_ref )
			return *this;

	
		DeleteRefCount();

		if( !rhs.m_ref )
			return *this;

		m_ref = rhs.m_ref;
		m_ref->IncRef();
		return *this;
	}

	
	virtual ~wxFNBSmartPtr()
	{
		DeleteRefCount();
	}

	
	void Reset(type_ptr ptr)
	{	
		DeleteRefCount();
		CreateFresh( ptr );
	}

	
	type_ptr Get()
	{
		return m_ref->GetData();
	}

	
	type_ptr operator->() const 
	{
		return m_ref->GetData();
	}

	
	T& operator*() const
	{
		return *(m_ref->GetData());
	}

	
	bool operator!() const
	{
		if( !m_ref )
			return true;

		return m_ref->GetData() == NULL;
	}

private:
	void DeleteRefCount()
	{
	
		if( m_ref )
		{
			if( m_ref->GetRefCount() == 1 )
			{
				delete m_ref;
				m_ref = NULL;
			}
			else
				m_ref->DecRef();
		}
	};

	void CreateFresh(type_ptr ptr)
	{
		m_ref = new SmartPtrRef( ptr );
	}
};

#endif // FNB_SMART_PTR_H
